import { VxeMenuPropTypes } from 'vxe-pc-ui';
import { RouteRecordRaw } from 'vue-router';
import Lodash from 'lodash';
import { SystemRoleMenuInfoVO } from '@/entiy/vo/SystemRoleMenuInfoVO.ts';
import { LocalMenuInfoVO } from '@/entiy/vo/LocalMenuInfoVO.ts';

export class MenuUtils {

    /**
     * 将 Vue Router 路由配置转换为 vxe-table 的菜单数据格式
     *
     * @param routes           本地 Vue Router 路由配置数组
     * @param roleMenuInfoList 角色配置的菜单
     */
    public static convertRouteToVxeMenu (routes: Array<RouteRecordRaw>, roleMenuInfoList: Array<SystemRoleMenuInfoVO>): VxeMenuPropTypes.Options {
        // 判空校验
        if (Lodash.isEmpty(roleMenuInfoList)) {
            console.error('角色菜单 RoleMenuInfoList 为空');
            return [];
        }

        // 获取角色编码（同一个用户的角色编码相同，取第一个即可）
        const roleMenuInfo: SystemRoleMenuInfoVO = roleMenuInfoList[0];
        const roleCode = roleMenuInfo.roleCode;

        // RoleMenuInfoList 转换成 Set
        const routeNameSet = new Set(roleMenuInfoList.map((item) => item.routeName));
        console.log('角色编码:', roleCode);
        console.log('角色配置的菜单所对应的路由:', routeNameSet);

        for (let route of routes) {
            const isRootMenu = route.meta?.isRootMenu;
            if (isRootMenu === 'undefined') {
                continue;
            }

            const children = route.children;
            if (!children || children.length === 0) {
                continue;
            }

            if (isRootMenu === true) {
                return this.convertRoutesToVxeMenu(children, roleCode, routeNameSet);
            }
        }

        console.error('路由配置中无 RootMenu 节点');
        return [];
    }

    /**
     * 将 Vue Router 路由配置转换为 vxe-table 的菜单数据格式
     *
     * @param routes       本地 Vue Router 路由配置数组
     * @param roleCode     角色编码
     * @param routeNameSet 角色配置的菜单对应的路由名称编码
     * @returns vxe-menu 的菜单数据格式
     */
    public static convertRoutesToVxeMenu (routes: Array<RouteRecordRaw>, roleCode: string, routeNameSet: Set<string>): VxeMenuPropTypes.Options {
        const menuList: VxeMenuPropTypes.Options = [];

        for (let route of routes) {
            const isMenu = route.meta?.isMenu as boolean;
            if (!isMenu) {
                continue;
            }

            // 路由名称
            const routeName = route.name?.toString().trim();
            if (!routeName || routeName === '') {
                continue;
            }

            // 路由标题
            const routeTitle = route.meta?.title as string;
            if (!routeTitle) {
                continue;
            }

            // 当前路由
            const menuItem: VxeMenuPropTypes.MenuOption = {
                name: routeName,
                title: routeTitle,
                icon: route.meta?.icon as string,
            };

            // 非超级管理员角色，只显示角色配置的菜单
            if (roleCode !== 'D364D6719E4C499E854817CE62CF874C') {
                if (route.children && route.children.length > 0) {
                    // 如果有子节点，判断配置的路由名称在子节点或孙子节点中配置过
                    let hasRouteWithName = false;
                    for (let name of routeNameSet) {
                        hasRouteWithName = this.hasRouteWithName(route.children, name);
                    }

                    // 子节点或孙子节点中配置没有匹配，说明没有子菜单，当前路由对应的菜单不展示
                    if (!hasRouteWithName) {
                        continue;
                    }
                } else {
                    // 无子节点，判断当前节点是否否有关联的菜单被配置过
                    if (!routeNameSet.has(routeName)) {
                        continue;
                    }
                }
            }

            // 如果路由果有子路由项，则递归处理子路由
            if (route.children && route.children.length > 0) {
                menuItem.children = this.convertRoutesToVxeMenu(route.children, roleCode, routeNameSet);
            } else {
                // 如果没有子路由项，则绑定菜单跳转的路由
                menuItem.routerLink = {
                    name: routeName,
                };
            }

            menuList.push(menuItem);
        }
        return menuList;
    }

    /*
    * 在子节点或者孙子节点中是否指定名称的路由
    *
    * @param routes 路由数组
    * @param name   要查找的路由名称
    * @returns 是否找到匹配的路由
    */
    public static hasRouteWithName (routes: Array<RouteRecordRaw>, name: string) {
        for (const route of routes) {
            // 如果当前路由的name匹配，直接返回true
            if (route.name === name) {
                return true;
            }

            // 如果当前路由有子路由，递归查找子路由
            if (route.children && route.children.length > 0) {
                // 如果在子路由中找到匹配的，返回 true
                if (this.hasRouteWithName(route.children, name)) {
                    return true;
                }
            }
        }

        // 遍历完所有路由都没找到匹配的，返回false
        return false;
    }

    /**
     * 将嵌套的路由结构平铺展开成 {name, title} 格式的菜单数据
     *
     * @param routes 嵌套的路由数据
     */
    public static flattenRouteToMenu (routes: Array<RouteRecordRaw>): Array<LocalMenuInfoVO> {
        for (let route of routes) {
            const isRootMenu = route.meta?.isRootMenu;
            if (isRootMenu === 'undefined') {
                continue;
            }

            const children = route.children;
            if (!children || children.length === 0) {
                continue;
            }

            if (isRootMenu === true) {
                return this.flattenRoutesToMenu(route.name as string, children, '');
            }
        }
        return [];
    }

    /**
     * 将嵌套的路由结构平铺展开成 {name, title} 格式的菜单数据
     *
     * @param parentRouteName  路由名称
     * @param childRoutes      嵌套的路由数据
     * @param parentTitle      父节点的 title（用于递归拼接）
     * @returns 平铺后的数组
     */
    public static flattenRoutesToMenu (parentRouteName: string, childRoutes: Array<RouteRecordRaw>, parentTitle = ''): Array<LocalMenuInfoVO> {
        let resultArray: Array<LocalMenuInfoVO> = [];

        childRoutes.forEach(route => {
            // 如果有 children，则不展开当前节点，而是递归处理子节点
            if (route.children && route.children.length > 0) {
                // 递归处理子节点，并传入当前节点的 title 作为父级 title
                if (!Lodash.isEmpty(route.meta?.title)) {
                    const title = route.meta?.title as string;
                    const childFlattened = this.flattenRoutesToMenu(route.name as string, route.children, title);
                    resultArray = resultArray.concat(childFlattened);
                }
            } else {
                // 如果没有 children，则直接展开当前节点
                resultArray.push({
                    parentRouteName: parentRouteName,
                    routeName: route.name as string,
                    menuTitle: parentTitle ? `${parentTitle}-${route.meta?.title}` : route.meta?.title as string ?? '',
                });
            }
        });

        return resultArray;
    }
}
